Slovenčina

Preskúmajte pokročilé techniky modifikácie požiadaviek pomocou Next.js middleware. Naučte sa riešiť zložité smerovanie, autentifikáciu, A/B testovanie a lokalizačné stratégie pre robustné webové aplikácie.

Okrajové prípady v Next.js Middleware: Zvládnutie vzorov modifikácie požiadaviek

Middleware v Next.js poskytuje výkonný mechanizmus na zachytávanie a úpravu požiadaviek predtým, ako sa dostanú k trasám vašej aplikácie. Táto schopnosť otvára širokú škálu možností, od jednoduchých kontrol autentifikácie až po zložité scenáre A/B testovania a stratégie internacionalizácie. Efektívne využitie middleware však vyžaduje hlboké porozumenie jeho okrajových prípadov a potenciálnych nástrah. Táto komplexná príručka skúma pokročilé vzory modifikácie požiadaviek, poskytuje praktické príklady a využiteľné poznatky, ktoré vám pomôžu vytvárať robustné a výkonné aplikácie v Next.js.

Pochopenie základov Next.js Middleware

Predtým, ako sa ponoríme do pokročilých vzorov, zopakujme si základy Next.js middleware. Middleware funkcie sa vykonávajú pred dokončením požiadavky, čo vám umožňuje:

Middleware funkcie sa nachádzajú v súbore middleware.js alebo middleware.ts vo vašom adresári /pages alebo /app (v závislosti od vašej verzie Next.js a nastavenia). Prijímajú objekt NextRequest reprezentujúci prichádzajúcu požiadavku a môžu vrátiť objekt NextResponse na riadenie následného správania.

Príklad: Základný middleware pre autentifikáciu

Tento príklad demonštruje jednoduchú kontrolu autentifikácie. Ak používateľ nie je autentifikovaný (napr. nemá platný token v cookie), je presmerovaný na prihlasovaciu stránku.


import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'

export function middleware(request: NextRequest) {
  const authToken = request.cookies.get('authToken')

  if (!authToken) {
    return NextResponse.redirect(new URL('/login', request.url))
  }

  return NextResponse.next()
}

export const config = {
  matcher: ['/protected/:path*'],
}

Tento middleware sa spustí iba pre trasy, ktoré zodpovedajú /protected/:path*. Kontroluje prítomnosť cookie authToken. Ak cookie chýba, používateľ je presmerovaný na stránku /login. V opačnom prípade sa požiadavke umožní pokračovať normálne pomocou NextResponse.next().

Pokročilé vzory modifikácie požiadaviek

Teraz sa pozrime na niektoré pokročilé vzory modifikácie požiadaviek, ktoré demonštrujú skutočnú silu Next.js middleware.

1. A/B testovanie pomocou cookies

A/B testovanie je kľúčová technika na optimalizáciu používateľských skúseností. Middleware môže byť použitý na náhodné priradenie používateľov k rôznym variantom vašej aplikácie a na sledovanie ich správania. Tento vzor sa spolieha na cookies na uchovanie priradeného variantu používateľa.

Príklad: A/B testovanie vstupnej stránky


import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'

const VARIANT_A = 'variantA'
const VARIANT_B = 'variantB'

export function middleware(request: NextRequest) {
  let variant = request.cookies.get('variant')?.value

  if (!variant) {
    // Randomly assign a variant
    variant = Math.random() < 0.5 ? VARIANT_A : VARIANT_B
    const response = NextResponse.next()
    response.cookies.set('variant', variant)
    return response
  }

  if (variant === VARIANT_A) {
    return NextResponse.rewrite(new URL('/variant-a', request.url))
  } else if (variant === VARIANT_B) {
    return NextResponse.rewrite(new URL('/variant-b', request.url))
  }

  return NextResponse.next()
}

export const config = {
  matcher: ['/'],
}

V tomto príklade, keď používateľ prvýkrát navštívi koreňovú cestu (/), middleware ho náhodne priradí buď k variantA alebo variantB. Tento variant sa uloží do cookie. Následné požiadavky od toho istého používateľa budú prepísané buď na /variant-a alebo /variant-b, v závislosti od ich priradeného variantu. To vám umožní servírovať rôzne vstupné stránky a sledovať, ktorá z nich má lepšie výsledky. Uistite sa, že máte vo svojej Next.js aplikácii definované trasy pre /variant-a a /variant-b.

Globálne zváženia: Pri vykonávaní A/B testovania zvážte regionálne rozdiely. Dizajn, ktorý rezonuje v Severnej Amerike, nemusí byť rovnako efektívny v Ázii. Mohli by ste použiť geolokačné údaje (získané prostredníctvom vyhľadávania IP adresy alebo preferencií používateľa) na prispôsobenie A/B testu konkrétnym regiónom.

2. Lokalizácia (i18n) s prepisovaním URL

Internacionalizácia (i18n) je nevyhnutná na oslovenie globálneho publika. Middleware môže byť použitý na automatické zistenie preferovaného jazyka používateľa a jeho presmerovanie na príslušnú lokalizovanú verziu vašej stránky.

Príklad: Presmerovanie na základe hlavičky `Accept-Language`


import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'

const SUPPORTED_LANGUAGES = ['en', 'fr', 'es', 'de']
const DEFAULT_LANGUAGE = 'en'

function getPreferredLanguage(request: NextRequest): string {
  const acceptLanguage = request.headers.get('accept-language')
  if (!acceptLanguage) {
    return DEFAULT_LANGUAGE
  }

  const languages = acceptLanguage.split(',').map((lang) => lang.split(';')[0].trim())

  for (const lang of languages) {
    if (SUPPORTED_LANGUAGES.includes(lang)) {
      return lang
    }
  }

  return DEFAULT_LANGUAGE
}

export function middleware(request: NextRequest) {
  const pathname = request.nextUrl.pathname

  // Check if there's an existing locale in the pathname
  if (
    SUPPORTED_LANGUAGES.some(
      (locale) => pathname.startsWith(`/${locale}/`) || pathname === `/${locale}`
    )
  ) {
    return NextResponse.next()
  }

  const preferredLanguage = getPreferredLanguage(request)

  return NextResponse.redirect(
    new URL(`/${preferredLanguage}${pathname}`, request.url)
  )
}

export const config = {
  matcher: [
    '/((?!api|_next/static|_next/image|favicon.ico).*)'
  ],
}

Tento middleware extrahuje hlavičku Accept-Language z požiadavky a určí preferovaný jazyk používateľa. Ak URL adresa ešte neobsahuje jazykovú predponu (napr. /en/about), middleware presmeruje používateľa na príslušnú lokalizovanú URL adresu (napr. /fr/about pre francúzštinu). Uistite sa, že máte vo svojom adresári `/pages` alebo `/app` vhodnú štruktúru priečinkov pre rôzne jazykové verzie. Napríklad budete potrebovať súbory `/pages/en/about.js` a `/pages/fr/about.js`.

Globálne zváženia: Uistite sa, že vaša i18n implementácia správne spracováva jazyky písané sprava doľava (napr. arabčina, hebrejčina). Zvážte tiež použitie siete na doručovanie obsahu (CDN) na servírovanie lokalizovaných zdrojov zo serverov bližšie k vašim používateľom, čím sa zlepší výkon.

3. Príznaky funkcií (Feature Flags)

Príznaky funkcií vám umožňujú povoliť alebo zakázať funkcie vo vašej aplikácii bez nasadenia nového kódu. To je obzvlášť užitočné pri postupnom zavádzaní nových funkcií alebo pri testovaní funkcií v produkčnom prostredí. Middleware môže byť použitý na kontrolu stavu príznaku funkcie a na zodpovedajúcu úpravu požiadavky.

Príklad: Povolenie beta funkcie


import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'

const BETA_FEATURE_ENABLED = process.env.BETA_FEATURE_ENABLED === 'true'

export function middleware(request: NextRequest) {
  if (BETA_FEATURE_ENABLED && request.nextUrl.pathname.startsWith('/new-feature')) {
    return NextResponse.next()
  }

  // Optionally redirect to a "feature unavailable" page
  return NextResponse.rewrite(new URL('/feature-unavailable', request.url))
}

export const config = {
  matcher: ['/new-feature/:path*'],
}

Tento middleware kontroluje hodnotu premennej prostredia BETA_FEATURE_ENABLED. Ak je nastavená na true a používateľ sa snaží získať prístup k trase pod /new-feature, požiadavke sa umožní pokračovať. V opačnom prípade je používateľ presmerovaný na stránku /feature-unavailable. Nezabudnite správne nakonfigurovať premenné prostredia pre rôzne prostredia (vývoj, staging, produkcia).

Globálne zváženia: Pri používaní príznakov funkcií zvážte právne dôsledky povolenia funkcií, ktoré nemusia byť v súlade s predpismi vo všetkých regiónoch. Napríklad funkcie súvisiace s ochranou osobných údajov môžu byť v niektorých krajinách potrebné deaktivovať.

4. Detekcia zariadení a adaptívne smerovanie

Moderné webové aplikácie musia byť responzívne a prispôsobovať sa rôznym veľkostiam obrazoviek a schopnostiam zariadení. Middleware môže byť použitý na detekciu typu zariadenia používateľa a na jeho presmerovanie na optimalizované verzie vašej stránky.

Príklad: Presmerovanie mobilných používateľov na mobilne optimalizovanú subdoménu


import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'
import { device } from 'detection'

export function middleware(request: NextRequest) {
  const userAgent = request.headers.get('user-agent')

  if (userAgent) {
    const deviceType = device(userAgent)

    if (deviceType.type === 'phone') {
      const mobileUrl = new URL(request.url)
      mobileUrl.hostname = 'm.example.com'
      return NextResponse.redirect(mobileUrl)
    }
  }

  return NextResponse.next()
}

export const config = {
  matcher: ['/'],
}

Tento príklad používa knižnicu `detection` na určenie typu zariadenia používateľa na základe hlavičky User-Agent. Ak je používateľ na mobilnom telefóne, je presmerovaný na subdoménu m.example.com (za predpokladu, že tam máte hosťovanú mobilne optimalizovanú verziu svojej stránky). Nezabudnite nainštalovať balíček `detection`: `npm install detection`.

Globálne zváženia: Uistite sa, že vaša logika detekcie zariadení zohľadňuje regionálne rozdiely v používaní zariadení. Napríklad, v niektorých rozvojových krajinách sú stále bežné jednoduché mobilné telefóny (feature phones). Zvážte použitie kombinácie detekcie User-Agent a techník responzívneho dizajnu pre robustnejšie riešenie.

5. Obohatenie hlavičiek požiadavky

Middleware môže pridať informácie do hlavičiek požiadavky predtým, ako ich spracujú trasy vašej aplikácie. To je užitočné na pridanie vlastných metadát, ako sú roly používateľa, stav autentifikácie alebo ID požiadavky, ktoré môže využiť vaša aplikačná logika.

Príklad: Pridanie ID požiadavky


import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'
import { v4 as uuidv4 } from 'uuid'

export function middleware(request: NextRequest) {
  const requestId = uuidv4()
  const response = NextResponse.next()
  response.headers.set('x-request-id', requestId)
  return response
}

export const config = {
  matcher: ['/api/:path*'], // Only apply to API routes
}

Tento middleware generuje jedinečné ID požiadavky pomocou knižnice uuid a pridáva ho do hlavičky x-request-id. Toto ID sa potom môže použiť na účely logovania, sledovania a ladenia. Nezabudnite nainštalovať balíček uuid: `npm install uuid`.

Globálne zváženia: Pri pridávaní vlastných hlavičiek dávajte pozor na limity veľkosti hlavičiek. Prekročenie týchto limitov môže viesť k neočakávaným chybám. Taktiež zabezpečte, aby všetky citlivé informácie pridané do hlavičiek boli riadne chránené, najmä ak je vaša aplikácia za reverzným proxy alebo CDN.

6. Vylepšenia bezpečnosti: Obmedzenie frekvencie požiadaviek (Rate Limiting)

Middleware môže slúžiť ako prvá línia obrany proti škodlivým útokom implementáciou obmedzenia frekvencie požiadaviek. To zabraňuje zneužitiu obmedzením počtu požiadaviek, ktoré môže klient urobiť v určitom časovom okne.

Príklad: Základné obmedzenie frekvencie pomocou jednoduchého úložiska


import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'

const requestCounts: { [ip: string]: number } = {}
const WINDOW_SIZE_MS = 60000; // 1 minute
const MAX_REQUESTS_PER_WINDOW = 100;

export function middleware(request: NextRequest) {
  const clientIP = request.ip || '127.0.0.1' // Get client IP, default to localhost for local testing

  if (!requestCounts[clientIP]) {
    requestCounts[clientIP] = 0;
  }

  requestCounts[clientIP]++;

  if (requestCounts[clientIP] > MAX_REQUESTS_PER_WINDOW) {
    return new NextResponse(
      JSON.stringify({ message: 'Too many requests' }),
      { status: 429, headers: { 'Content-Type': 'application/json' } }
    );
  }

  // Reset count after window
  setTimeout(() => {
    requestCounts[clientIP]--;
    if (requestCounts[clientIP] <= 0) {
        delete requestCounts[clientIP];
    }
  }, WINDOW_SIZE_MS);

  return NextResponse.next();
}

export const config = {
  matcher: ['/api/:path*'], // Apply to all API routes
}

Tento príklad udržiava jednoduché úložisko v pamäti (requestCounts) na sledovanie počtu požiadaviek z každej IP adresy. Ak klient prekročí MAX_REQUESTS_PER_WINDOW v rámci WINDOW_SIZE_MS, middleware vráti chybu 429 Too Many Requests. Dôležité: Toto je zjednodušený príklad a nie je vhodný pre produkčné prostredia, pretože sa neškáluje a je zraniteľný voči útokom typu denial-of-service. Pre produkčné použitie zvážte použitie robustnejšieho riešenia na obmedzenie frekvencie, ako je Redis alebo špecializovaná služba na obmedzenie frekvencie.

Globálne zváženia: Stratégie obmedzenia frekvencie by mali byť prispôsobené špecifickým vlastnostiam vašej aplikácie a geografickému rozloženiu vašich používateľov. Zvážte použitie rôznych limitov pre rôzne regióny alebo segmenty používateľov.

Okrajové prípady a potenciálne nástrahy

Hoci je middleware mocný nástroj, je dôležité byť si vedomý jeho obmedzení a potenciálnych nástrah:

Osvedčené postupy pre používanie Next.js Middleware

Aby ste maximalizovali výhody Next.js middleware a vyhli sa potenciálnym problémom, dodržiavajte tieto osvedčené postupy:

Záver

Middleware v Next.js ponúka výkonný spôsob, ako modifikovať požiadavky a prispôsobiť správanie vašej aplikácie na okraji siete (edge). Porozumením pokročilým vzorom modifikácie požiadaviek, ktoré boli prediskutované v tejto príručke, môžete vytvárať robustné, výkonné a globálne orientované aplikácie v Next.js. Nezabudnite dôkladne zvážiť okrajové prípady a potenciálne nástrahy a dodržiavať vyššie uvedené osvedčené postupy, aby ste zabezpečili, že vaše middleware funkcie budú spoľahlivé a udržiavateľné. Využite silu middleware na vytváranie výnimočných používateľských zážitkov a odomknite nové možnosti pre vaše webové aplikácie.